
import 'package:dio/dio.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:sqflite/sqflite.dart';
import 'package:ymt/api/apis.dart';
import 'package:ymt/db/offline_database_provider.dart';
import 'package:ymt/ui/main_page.dart';
import 'package:ymt/utils/request.dart';

import '../utils/nav.dart';

class SyncPage extends StatefulWidget{

  final _companyId;
  final _companyName;
  final _loginToken;
  SyncPage(this._companyId,this._companyName,this._loginToken);
  @override
  State<StatefulWidget> createState() {
    return PageState(_companyId,this._companyName,_loginToken);
  }
}

/// 同步一定需要网络
class PageState extends State<SyncPage>{

  final String KEY_COMPANY_UPDATE = "company_update_at";
  final String KEY_CATEGORY_UPDATE = "category_update_at";
  final String KEY_PRODUCT_UPDATE = "product_update_at";
  final String KEY_VARIANT_UPDATE = "variant_update_at";
  final String KEY_PICTURE_UPDATE = "picture_update_at";
  final String KEY_TAG_UPDATE = "tag_update_at";
  final String KEY_FILTER_UPDATE = "filter_update_at";
  final String KEY_SEARCH_UPDATE = "search_update_at";

  Dio dio;
  Database db;
  SharedPreferences prefs;
  final _companyId;
  final _companyName;
  final _loginToken;
  bool _syncAll = false;

  PageState(this._companyId,this._companyName, this._loginToken);

  @override
  void initState() {
    executeTask();
    super.initState();
  }

  executeTask() async {
    prefs = await SharedPreferences.getInstance();
    await OfflineDatabaseProvider().open((database){
      //先保证数据库得以运行
      db = database;
      initDio();
      syncCompanies({"id": _companyId});
    });
  }

  void initDio(){
    dio = Request.dio();
  }

  @override
  Widget build(BuildContext context) {
    // UI
    Widget content;
    var text = Container(child: Text("数据同步中,可能需要几分钟...", style: TextStyle(color: Colors.white,fontSize: 14),),margin: EdgeInsets.all(20),);
    content = Column(children: <Widget>[CircularProgressIndicator(),text],mainAxisAlignment: MainAxisAlignment.center,);
    return content;
  }


  syncCompanies(params) async {
    await dio.get(ApiPaths.COMPANY,queryParameters: params,
        onReceiveProgress: (int progress, int total) {
          String p = "$progress/$total";
          //print(p);
        })
      .then((response) async {
        print(response.data[0]);
        await db.insert(OfflineDatabaseProvider.TABLE_COMPANIES, response.data[0],conflictAlgorithm: ConflictAlgorithm.replace)
            .then((int id){
              print(id);

              // 分类流程
              syncStream(KEY_CATEGORY_UPDATE, SyncApiPaths.CATEGORIES, OfflineDatabaseProvider.TABLE_CATEGORIES, "id", (item) {
                return convertCategory(item);
              }, (result) {
                prefs.setString(KEY_CATEGORY_UPDATE, DateTime.now().toString());//更新保存时间
                print(result);
                productStream();
              }, (){
                //接口没有返回数据
                print("接口没有返回数据");
                productStream();
              });
           });
      });
  }

  Map<String, dynamic> convertCategory(item){
    Map<String,dynamic> map = Map();
    map["updated_at"] = item["updated_at"];
    map["id"] = item["id"];
    map["name"] = item["name"];
    map["is_parent"] = item["is_parent"];
    map["position"] = item["position"];
    map["company_id"] = item["company_id"];
    map["parent_id"] = item["parent_id"];
    map["retail_rate"] = item["retail_rate"];
    return map;
  }

  /// 处理Product
  productStream(){
    syncStream(KEY_PRODUCT_UPDATE, SyncApiPaths.PRODUCTS, OfflineDatabaseProvider.TABLE_PRODUCTS, "id", (item) {
      return convertProduct(item);
    }, (result) {
      prefs.setString(KEY_PRODUCT_UPDATE, DateTime.now().toString());//更新保存时间
      print(result);
      variantStream();
    }, (){
      //接口没有返回数据
      print("接口没有返回数据");
      variantStream();
    });
  }

  Map<String, dynamic> convertProduct(item){
    Map<String,dynamic> map = Map();
    map["id"] = item["id"];
    map["name"] = item["name"];
    map["visible"] = item["visible"];
    map["product_category_id"] = item["product_category_id"];
    map["position"] = item["position"];
    map["thumb_picture"] = item["thumb_picture"];
    map["main_picture"] = item["main_picture"];
    map["company_id"] = item["company_id"];
    map["retail_rate"] = item["retail_rate"];
    return map;
  }

  /// 处理Variant
  variantStream(){
    syncStream(KEY_VARIANT_UPDATE, SyncApiPaths.VARIANTS, OfflineDatabaseProvider.TABLE_VARIANTS, "id", (item) {
      return convertVariant(item);
    }, (result) {
      prefs.setString(KEY_VARIANT_UPDATE, DateTime.now().toString());//更新保存时间
      print(result);
      pictureStream();
    }, (){
      //接口没有返回数据
      print("接口没有返回数据");
      pictureStream();
    });
  }

  Map<String, dynamic> convertVariant(item){
    Map<String,dynamic> map = Map();
    map["id"] = item["id"];
    map["options_text"] = item["options_text"];
    map["price"] = item["price"];
    map["product_id"] = item["product_id"];
    map["retail_rate"] = item["retail_rate"];
    return map;
  }

  /// 处理Pictures
  pictureStream(){
    syncStream(KEY_PICTURE_UPDATE, SyncApiPaths.PICTURES, OfflineDatabaseProvider.TABLE_PICTURES, "id", (item) {
      return convertPicture(item);
    }, (result) {
      prefs.setString(KEY_PICTURE_UPDATE, DateTime.now().toString());//更新保存时间
      print(result);
      tagsStream();
    }, (){
      //接口没有返回数据
      print("接口没有返回数据");
      tagsStream();
    });
  }

  Map<String, dynamic> convertPicture(item){
    Map<String,dynamic> map = Map();
    map["id"] = item["id"];
    map["file"] = item["file"];
    map["product_id"] = item["product_id"];
    return map;
  }

  /// 处理Tags
  tagsStream(){
    syncStream(KEY_TAG_UPDATE, SyncApiPaths.SEARCH_TAGS, OfflineDatabaseProvider.TABLE_SEARCH_TAGS, "id", (item) {
      return convertTags(item);
    }, (result) {
      prefs.setString(KEY_TAG_UPDATE, DateTime.now().toString());//更新保存时间
      print(result);
      filtersStream();
    }, (){
      //接口没有返回数据
      print("接口没有返回数据");
      filtersStream();
    });
  }

  Map<String, dynamic> convertTags(item){
    Map<String,dynamic> map = Map();
    map["id"] = item["id"];
    map["name"] = item["name"];
    return map;
  }

  /// 处理FilterOptions
  filtersStream(){
    if(prefs.containsKey(KEY_FILTER_UPDATE)) {
      searchTagsStream();
    }else{
      Batch batch = db.batch();
      requestMap(SyncApiPaths.FILTER_OPTIONS, null, (response) {
        response.data["data"].map((item) {
          //print(item);
          batch.insert(
              OfflineDatabaseProvider.TABLE_FILTER_OPTIONS, convertFilter(item),
              conflictAlgorithm: ConflictAlgorithm.replace);
        }).toList();
        response.data["maps"].map((item) {
          //print(item);
          batch.insert(OfflineDatabaseProvider.TABLE_FILTER_OPTIONS_MAPS,
              convertFilter(item),
              conflictAlgorithm: ConflictAlgorithm.replace);
        }).toList();
        batch.commit(continueOnError: true).then((result) {
          print(result);
          prefs.setString(KEY_FILTER_UPDATE, DateTime.now().toString()); //更新保存时间
          searchTagsStream();
        });
      }, () {
        print("接口没有返回数据");
        searchTagsStream();
      });
    }
  }

  Map<String, dynamic> convertFilter(item){
    Map<String,dynamic> map = Map();
    map["name"] = item["name"];
    map["value"] = item["values"];
    return map;
  }

  /// 处理searchTags
  searchTagsStream(){
    syncStream(KEY_SEARCH_UPDATE, SyncApiPaths.PRODUCT_SEARCH_TAGS, OfflineDatabaseProvider.TABLE_PRODUCT_SEARCH_TAGS, "id", (item) {
      return convertSearchTags(item);
    }, (result) {
      prefs.setString(KEY_SEARCH_UPDATE, DateTime.now().toString());//更新保存时间
      print(result);
      onComplete();
    }, (){
      //接口没有返回数据
      print("接口没有返回数据");
      onComplete();
    });
  }

  Map<String, dynamic> convertSearchTags(item){
    Map<String,dynamic> map = Map();
    map["id"] = item["id"];
    map["search_tag_id"] = item["search_tag_id"];
    map["source_id"] = item["source_id"];
    map["product_id"] = item["product_id"];
    map["position"] = item["position"];
    map["company_id"] = item["company_id"];
    return map;
  }


  /// 同步流，处理是否全量和增量更新
  syncStream(keyUpdateTime, syncUrlPath, table, primaryKey, convert, onValue, onEmpty) async {
    Batch batch = db.batch();
    if(prefs.containsKey(keyUpdateTime) && !_syncAll){
      //包含key则表示已经做过全量更新
      var time = "2019-12-01";
      time = prefs.getString(keyUpdateTime);
      /// 如果未超过24小时，不更新直接进入主页
      DateTime updateTime = DateTime.parse(time);
      DateTime current = DateTime.now();
      Duration duration = current.difference(updateTime);
      print(duration);
      if(duration.inHours < 24){
        onComplete();
      }else{
        fetchAndDelete(syncUrlPath, time, table, primaryKey, batch, (result){
          print(result);//删除的结果
          fetchAndUpdate(syncUrlPath, table, convert, batch, time, onValue, onEmpty);
        },() {//没有需要删除的
          fetchAndUpdate(syncUrlPath, table, convert, batch, time, onValue, onEmpty);
        });
      }
    }else{
      fetchAndInsert(syncUrlPath, table, convert, batch, onValue, onEmpty);
    }
  }

  /// 请求数据，然后保存至数据库
  void fetchAndInsert(syncUrlPath, table, convert, Batch batch, onCommit, onEmpty) {
    requestMap(syncUrlPath, {"id":_companyId,"action":"get_all"}, (response) async {
      response.data.map((item) async {
        batch.insert(table, convert(item),
            conflictAlgorithm: ConflictAlgorithm.replace);
      }).toList(); //执行toList才会转换
      await batch.commit(continueOnError: true).then(onCommit);
    }, onEmpty);
  }

  void fetchAndDelete(syncUrlPath, updateTime, table, primaryKey, Batch batch, onCommit, onEmpty) {
    requestMap(syncUrlPath, {"id":_companyId, "action":"get_deleted", "time":updateTime}, (response) async {//get_deleted
      response.data.map((item) async {
        batch.delete(
            table, where: '$primaryKey = ?', whereArgs: [item[primaryKey]]);
      }).toList(); //执行toList才会转换
      await batch.commit(continueOnError: true).then(onCommit);
    }, onEmpty);
  }

  void fetchAndUpdate(syncUrlPath, table, convert, Batch batch, updateTime, onCommit, onEmpty) {
    requestMap(syncUrlPath, {"id":_companyId, "action":"get_updated", "time":updateTime}, (response) async {//get_updated
      response.data.map((item) async {
        batch.update(table, convert(item));
      }).toList(); //执行toList才会转换
      await batch.commit(continueOnError: true).then(onCommit);
    }, onEmpty);
  }

  /// 发起同步请求并交付回调，[syncUrlPath]为同步请求路径，[param]为请求参数，[onResult]为请求结果转换的map
  requestMap(syncUrlPath, param, onResult, onEmpty) async {
    // 1.请求接口数据
    await dio.get(syncUrlPath, queryParameters: param, onReceiveProgress: (int progress, int total) {
      String p = "$progress/$total";
      //print(p);
    }).then((response) async {
      if(response.data.length < 1){
        onEmpty();//返回空参数方法
      }else {
        onResult(response);
      }
    });
  }

  onComplete(){
    Nav.destroyNav(context, MainPage(_companyId, _companyName, _loginToken));
  }

}